package com.coldworks.base.util;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

import org.apache.log4j.Level;

import com.coldworks.base.manager.BasePrefManager;
import com.coldworks.base.manager.BaseStorageManager;

import de.mindpipe.android.logging.log4j.LogConfigurator;

import android.content.Context;
import android.util.Log;

public class BaseLoggerFactory {
	private static Context inited_ctx = null;
	private static int inited_versionCode = -1;

	public static void init(Context ctx, int versionCode, boolean logcat) {
		if (inited_ctx != null || inited_versionCode >= 0) {
			return;
		}
		inited_ctx = ctx;
		inited_versionCode = versionCode;
		File logFile = BaseStorageManager.getInstance().getLogFile();
		File logErrFile = BaseStorageManager.getInstance().getLogErrFile();
		if (logFile != null && logErrFile != null) { // log文件存在 && err路径存在
			if (isLogReporting()) { // 需要发送错误
				if (logErrFile.exists()) { // err文件存在，这是不正常的，说明上次发送没成功，这次还在等待发送
					Log.i(BaseCONST.LOGGER.TAG, "[LOG] <init> "
							+ "errlog found");
				} else { // err文件不存在，这说明上次发生过异常，需要在本次发送，所以接下来要生成错误文件
					try {
						logErrFile.createNewFile();
						if (logFile.renameTo(logErrFile)) {
							Log.i(BaseCONST.LOGGER.TAG, "[LOG] <init> "
									+ "errlog backuped");
						} else {
							Log.w(BaseCONST.LOGGER.TAG, "[LOG] <init> "
									+ "errlog backup err");
						}
					} catch (IOException e) {
						Log.w(BaseCONST.LOGGER.TAG, "[LOG] <init> "
								+ "errlog backup err");
					}
				}
			} else { // 不需要发送错误
				if (logErrFile.exists()) { // 错误文件存在，其实它不必要存在了
					logErrFile.delete();
					Log.i(BaseCONST.LOGGER.TAG, "[LOG] <init> "
							+ "errlog cleaned");
				} else { // 错误文件不存在，这是正常的
					Log.i(BaseCONST.LOGGER.TAG, "[LOG] <init> "
							+ "no err before");
				}
			}
			try {
				if (logFile.exists()) {
					logFile.delete();
				}
				logFile.createNewFile();
				Log.i(BaseCONST.LOGGER.TAG, "[LOG] <init> " + "newlog created");

				if (logcat) {
					startLoggingToFile();
				} else {
					stopLoggingToFile();
				}

			} catch (IOException e) {
				Log.w(BaseCONST.LOGGER.TAG, "[LOG] <init> " + "log file io err");
			}
		} else { // logFile == null || logErrFile == null
			Log.w(BaseCONST.LOGGER.TAG, "[LOG] <init> " + "log file create err");
			stopLoggingToFile();
		}
	}

	public static Boolean isLogReporting() {
		if (inited_ctx == null) {
			Log.w(BaseCONST.LOGGER.TAG, "[LOG] <isLogReporting> "
					+ "never inited");
			return false;
		}
		return BasePrefManager.getInstance().getIntFromPrefs(inited_ctx,
				BaseCONST.KEY.LOG_REPORTING, 0) == inited_versionCode;
	}

	public static Boolean isLogReported() {
		if (inited_ctx == null) {
			Log.w(BaseCONST.LOGGER.TAG, "[LOG] <isLogReported> "
					+ "never inited");
			return false;
		}
		return BasePrefManager.getInstance().getIntFromPrefs(inited_ctx,
				BaseCONST.KEY.LOG_REPORTED, 0) == inited_versionCode;
	}

	public static long notifyStop() {
		File log = BaseStorageManager.getInstance().getLogFile();
		if (log != null) {
			if (log.length() > BaseCONST.LOGGER.LOG_MAX_LENGTH) {
				stopLoggingToFile();
			}
			return log.length();
		} else {
			return 0;
		}
	}

	public static void startLoggingToFile() {
		File logFile = BaseStorageManager.getInstance().getLogFile();
		final LogConfigurator logConfigurator = new LogConfigurator();
		logConfigurator.setRootLevel(Level.DEBUG);
		logConfigurator.setLevel("org.apache", Level.ERROR);
		logConfigurator.setUseLogCatAppender(true);
		logConfigurator.setLogCatPattern("<%L:%M> %m%n");
		logConfigurator.setUseFileAppender(true);
		logConfigurator.setFileName(logFile.getAbsolutePath());
		logConfigurator.setMaxFileSize(BaseCONST.LOGGER.LOG_MAX_LENGTH);
		logConfigurator.setFilePattern("%d %-5p [%c{1}] <%L:%M> %m%n");
		logConfigurator.setImmediateFlush(true);
		logConfigurator.configure();
	}

	public static void stopLoggingToFile() {
		LogConfigurator logConfigurator = new LogConfigurator();
		logConfigurator.setRootLevel(Level.DEBUG);
		logConfigurator.setLevel("org.apache", Level.ERROR);
		logConfigurator.setUseLogCatAppender(true);
		logConfigurator.setLogCatPattern("<%L:%M> %m%n");
		logConfigurator.setImmediateFlush(true);
		logConfigurator.setUseFileAppender(false);
		logConfigurator.configure();
	}

	public static void setLogReporting() {
		if (inited_ctx == null) {
			return;
		}
		try {
			BasePrefManager.getInstance().setIntToPrefs(inited_ctx,
					BaseCONST.KEY.LOG_REPORTING, inited_versionCode);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void setLogReported() {
		if (inited_ctx == null) {
			Log.w(BaseCONST.LOGGER.TAG, "[LOG] <setLogReported> "
					+ "never inited");
			return;
		}
		BasePrefManager.getInstance().setIntToPrefs(inited_ctx,
				BaseCONST.KEY.LOG_REPORTED, inited_versionCode);
		Log.i(BaseCONST.LOGGER.TAG, "[LOG] <setLogReported> " + "done");
	}

	public static void coredump(Throwable e) {
		String path;
		File rootDir = BaseStorageManager.getInstance().getRootDir();
		File backupDir = BaseStorageManager.getInstance().getBackupDir();
		if (backupDir == null) {
			if (rootDir == null) {
				e.printStackTrace();
				return;
			} else {
				path = rootDir.getAbsolutePath() + File.separator + "coredump";
			}
		} else {
			path = backupDir.getAbsolutePath() + File.separator + "coredump";
		}

		File testFile = new File(path);
		if (testFile.exists()) {
			testFile.delete();
		}
		try {
			testFile.createNewFile();
			FileWriter fw = new FileWriter(testFile);
			PrintWriter pw = new PrintWriter(fw);
			e.printStackTrace(pw);
			pw.flush();
			pw.close();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}
}
